#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include "bmp.h"
#include "lcd.h"

/*
功能：显示图片
参数：
	x0，y0 ：要在lcd的那个位置显示图片
	bmp_pathname:bmp图片的路径名
返回值：
	1 显示成功
	0 显示失败
*/
int bmp_display(const char*bmp_pathname, int x0, int y0)
{
	//1.打开bmp图片
    int bmp_fd = open(bmp_pathname, O_RDONLY);
    if (-1 == bmp_fd)
    {
        perror("open fail");
        return 0;
    }

    unsigned char buf[4] = {0};

    //2.判断是否为bmp图片
    read(bmp_fd, buf, sizeof(buf));
    if (buf[0]!=0x42 || buf[1]!=0x4d)
    {
        printf("not bmp\n");
        close(bmp_fd);
    }

	//3.获取bmp图片的属性 宽高深
    //获取bmp宽度
    lseek(bmp_fd, 0x12, SEEK_SET);
    read(bmp_fd, buf, sizeof(buf));
    int width = buf[3]<<24 | buf[2]<<16 | buf[1]<<8 | buf[0];
	printf("width = %d\n", width);
    
    //获取bmp高度
    lseek(bmp_fd, 0x16, SEEK_SET);
    read(bmp_fd, buf, sizeof(buf));
    int height = buf[3]<<24 | buf[2]<<16 | buf[1]<<8 | buf[0];
    printf("height = %d\n", height);
	
    //获取bmp色深
    lseek(bmp_fd, 0x1c, SEEK_SET);
    read(bmp_fd, buf, sizeof(buf));
    int depth = buf[1]<<8 | buf[0];
	printf("depth = %d\n", depth);
	
    //判断色深是不是24或32
    if (depth != 24 && depth != 32)
    {
        printf("not use %d depth.\n", depth);
        close(bmp_fd);
    }

    //4.获取像素素组
    int line_valid_bytes = abs(width) * depth / 8;//一行的有效字节数
    int line_bytes;//一行的字节数
    int laizi = 0;//癞子数
    if (line_valid_bytes%4)//获取癞子数
    {
        laizi = 4-line_valid_bytes%4;
    }
    line_bytes = line_valid_bytes + laizi;//一行的字节数 = 癞子数加上一行有效字节数
    int total_bytes = line_bytes * abs(height);//像素数组的大小
    
	//向内存申请total_bytes的大小用于存放像素数组
    char *piexl = malloc(total_bytes);
	//跳转到图片数据中像素数组的位置
    lseek(bmp_fd, 54, SEEK_SET);
	//将图片像素数组中的数据读取出来保存到我们之前申请的堆空间p中
    read(bmp_fd, piexl, total_bytes);

	//5.在屏幕上显示这些像素点
	//读取像素点字节-》ARGB-》在屏幕上进行显示
    int a = 0,r,g,b;//颜色argb a为高位 b为低位
    int color;
    int i = 0;//用来遍历piexl中的数据
    int x, y;//用来遍历像素数据行和列
    int x1, y1;//用来存放图片中的某个点画在lcd屏幕上实际的坐标值
    for (y = 0; y < abs(height); y++)
    {
        for (x = 0; x < abs(width); x++)
        {
			//a r g b 0xargb 小端模式 b g r a
            b = piexl[i++];
            g = piexl[i++];
            r = piexl[i++];
            if (depth == 32)
                a = piexl[i++];

            color = a<<24 | r<<16 | g<<8 | b;//组装颜色
			
			//在屏幕对应位置进行显示
            x1 = width>0 ? x0+x : (x0+abs(width)-1-x);
            y1 = height>0 ? (y0+abs(height)-1-y) : y0+y;
            lcd_draw_point(x1, y1, color);
        }
		
		//每一行都跳过癞子
        i+=laizi;
    }
	
	free(piexl);//释放堆空间
    close(bmp_fd);//关闭图片
    return 1;
}